added Feb 2001 SDK
[windows-sources.git] / shared source / sscli20 / jscript / engine / return.cs
blob2f1888c70c790fb0c1111df706adb165cc1e7d8f
1 // ==++==
2 //
3 //
4 // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
5 //
6 // The use and distribution terms for this software are contained in the file
7 // named license.txt, which can be found in the root of this distribution.
8 // By using this software in any fashion, you are agreeing to be bound by the
9 // terms of this license.
10 //
11 // You must not remove this notice, or any other, from this software.
12 //
13 //
14 // ==--==
16 namespace Microsoft.JScript {
18 using System;
19 using System.Reflection;
20 using System.Reflection.Emit;
22 internal sealed class Return : AST{
23 private Completion completion;
24 private AST operand;
25 private FunctionScope enclosingFunctionScope;
26 private bool leavesFinally;
28 internal Return(Context context, AST operand, bool leavesFinally)
29 : base(context) {
30 this.completion = new Completion();
31 this.completion.Return = true;
32 this.operand = operand;
33 ScriptObject scope = Globals.ScopeStack.Peek();
34 while (!(scope is FunctionScope)){
35 scope = scope.GetParent();
36 if (scope == null){
37 this.context.HandleError(JSError.BadReturn);
38 scope = new FunctionScope(null);
41 this.enclosingFunctionScope = ((FunctionScope)scope);
42 if (this.operand != null && this.enclosingFunctionScope.returnVar == null)
43 this.enclosingFunctionScope.AddReturnValueField();
44 this.leavesFinally = leavesFinally;
47 internal override Object Evaluate(){
48 if (this.operand != null)
49 this.completion.value = this.operand.Evaluate();
50 return this.completion;
53 internal override bool HasReturn(){
54 return true;
57 internal override AST PartiallyEvaluate(){
58 if (this.leavesFinally)
59 this.context.HandleError(JSError.BadWayToLeaveFinally);
60 if (this.operand != null){
61 this.operand = this.operand.PartiallyEvaluate();
62 if (this.enclosingFunctionScope.returnVar != null)
63 if (this.enclosingFunctionScope.returnVar.type == null){
64 this.enclosingFunctionScope.returnVar.SetInferredType(this.operand.InferType(this.enclosingFunctionScope.returnVar), this.operand);
65 }else
66 Binding.AssignmentCompatible(this.enclosingFunctionScope.returnVar.type.ToIReflect(), this.operand, this.operand.InferType(null), true);
67 else{ //returning something from a function explicitly typed as Void
68 this.context.HandleError(JSError.CannotReturnValueFromVoidFunction);
69 this.operand = null;
71 }else if (this.enclosingFunctionScope.returnVar != null)
72 this.enclosingFunctionScope.returnVar.SetInferredType(Typeob.Object, null);
73 return this;
76 internal override void TranslateToIL(ILGenerator il, Type rtype){
77 //This assumes that rtype == Void.class.
78 this.context.EmitLineInfo(il);
79 if (this.operand != null)
80 this.operand.TranslateToIL(il, this.enclosingFunctionScope.returnVar.FieldType);
81 else if (this.enclosingFunctionScope.returnVar != null){
82 il.Emit(OpCodes.Ldsfld, CompilerGlobals.undefinedField);
83 Convert.Emit(this, il, Typeob.Object, this.enclosingFunctionScope.returnVar.FieldType);
85 if (this.enclosingFunctionScope.returnVar != null)
86 il.Emit(OpCodes.Stloc, (LocalBuilder)this.enclosingFunctionScope.returnVar.GetMetaData());
87 if (this.leavesFinally){
88 il.Emit(OpCodes.Newobj, CompilerGlobals.returnOutOfFinallyConstructor);
89 il.Emit(OpCodes.Throw);
90 }else if (compilerGlobals.InsideProtectedRegion)
91 il.Emit(OpCodes.Leave, this.enclosingFunctionScope.owner.returnLabel);
92 else
93 il.Emit(OpCodes.Br, this.enclosingFunctionScope.owner.returnLabel);
96 internal override void TranslateToILInitializer(ILGenerator il){
97 if (this.operand != null)
98 this.operand.TranslateToILInitializer(il);